home *** CD-ROM | disk | FTP | other *** search
/ MacAddict 83 / MacAddict_083_2003-07.iso / mac / Software / Development / VLC Source 0.5.3.dmg / src / extras / dirent.c < prev    next >
C/C++ Source or Header  |  2002-11-13  |  7KB  |  348 lines

  1. /*
  2.  * dirent.c
  3.  *
  4.  * Derived from DIRLIB.C by Matt J. Weinstein 
  5.  * This note appears in the DIRLIB.H
  6.  * DIRLIB.H by M. J. Weinstein   Released to public domain 1-Jan-89
  7.  *
  8.  * Updated by Jeremy Bettis <jeremy@hksys.com>
  9.  * Significantly revised and rewinddir, seekdir and telldir added by Colin
  10.  * Peters <colin@fu.is.saga-u.ac.jp>
  11.  *    
  12.  * $Revision: 1.6 $
  13.  * $Author: sam $
  14.  * $Date: 2002/11/13 20:51:04 $
  15.  *
  16.  */
  17.  
  18. #include "config.h"
  19.  
  20. #include <stdlib.h>
  21. #ifdef HAVE_ERRNO_H
  22. #   include <errno.h>
  23. #else
  24.     static int errno;
  25.     /* FIXME: anything clever to put here? */
  26. #   define EFAULT 12
  27. #   define ENOTDIR 12
  28. #   define ENOENT 12
  29. #   define ENOMEM 12
  30. #   define EINVAL 12
  31. #endif
  32. #include <string.h>
  33. #ifndef UNDER_CE
  34. #   include <io.h>
  35. #   include <direct.h>
  36. #endif
  37.  
  38. #define WIN32_LEAN_AND_MEAN
  39. #include <windows.h> /* for GetFileAttributes */
  40.  
  41. #include "dirent.h"
  42.  
  43. #define SUFFIX    "*"
  44. #define    SLASH    "\\"
  45.  
  46. /*
  47.  * opendir
  48.  *
  49.  * Returns a pointer to a DIR structure appropriately filled in to begin
  50.  * searching a directory.
  51.  */
  52. DIR * 
  53. opendir (const CHAR *szPath)
  54. {
  55.   DIR *nd;
  56.   unsigned int rc;
  57.   CHAR szFullPath[MAX_PATH];
  58.     
  59.   errno = 0;
  60.  
  61.   if (!szPath)
  62.     {
  63.       errno = EFAULT;
  64.       return (DIR *) 0;
  65.     }
  66.  
  67.   if (szPath[0] == '\0')
  68.     {
  69.       errno = ENOTDIR;
  70.       return (DIR *) 0;
  71.     }
  72.  
  73.   /* Attempt to determine if the given path really is a directory. */
  74.   rc = GetFileAttributes (szPath);
  75.   if (rc == -1)
  76.     {
  77.       /* call GetLastError for more error info */
  78.       errno = ENOENT;
  79.       return (DIR *) 0;
  80.     }
  81.   if (!(rc & FILE_ATTRIBUTE_DIRECTORY))
  82.     {
  83.       /* Error, entry exists but not a directory. */
  84.       errno = ENOTDIR;
  85.       return (DIR *) 0;
  86.     }
  87.  
  88.   /* Make an absolute pathname.  */
  89. #if defined( UNDER_CE )
  90.   if (szPath[0] == '\\' || szPath[0] == '/')
  91.     {
  92.       sprintf (szFullPath, MAX_PATH, "%s", szPath);
  93.       szFullPath[0] = '\\';
  94.     }
  95.   else
  96.     {
  97.       /* FIXME: if I wasn't lazy, I'd check for overflows here. */
  98.       sprintf (szFullPath, MAX_PATH, "\\%s", szPath );
  99.     }
  100. #else
  101.   _fullpath (szFullPath, szPath, MAX_PATH);
  102. #endif
  103.  
  104.   /* Allocate enough space to store DIR structure and the complete
  105.    * directory path given. */
  106.   nd = (DIR *) malloc (sizeof (DIR) + strlen (szFullPath) + strlen (SLASH) +
  107.                strlen (SUFFIX));
  108.  
  109.   if (!nd)
  110.     {
  111.       /* Error, out of memory. */
  112.       errno = ENOMEM;
  113.       return (DIR *) 0;
  114.     }
  115.  
  116.   /* Create the search expression. */
  117.   strcpy (nd->dd_name, szFullPath);
  118.  
  119.   /* Add on a slash if the path does not end with one. */
  120.   if (nd->dd_name[0] != '\0' &&
  121.       nd->dd_name[strlen (nd->dd_name) - 1] != '/' &&
  122.       nd->dd_name[strlen (nd->dd_name) - 1] != '\\')
  123.     {
  124.       strcat (nd->dd_name, SLASH);
  125.     }
  126.  
  127.   /* Add on the search pattern */
  128.   strcat (nd->dd_name, SUFFIX);
  129.  
  130.   /* Initialize handle to -1 so that a premature closedir doesn't try
  131.    * to call FindClose on it. */
  132.   nd->dd_handle = -1;
  133.  
  134.   /* Initialize the status. */
  135.   nd->dd_stat = 0;
  136.  
  137.   /* Initialize the dirent structure. ino and reclen are invalid under
  138.    * Win32, and name simply points at the appropriate part of the
  139.    * findfirst_t structure. */
  140.   nd->dd_dir.d_ino = 0;
  141.   nd->dd_dir.d_reclen = 0;
  142.   nd->dd_dir.d_namlen = 0;
  143.   nd->dd_dir.d_name = nd->dd_dta.cFileName;
  144.  
  145.   return nd;
  146. }
  147.  
  148.  
  149. /*
  150.  * readdir
  151.  *
  152.  * Return a pointer to a dirent structure filled with the information on the
  153.  * next entry in the directory.
  154.  */
  155. struct dirent *
  156. readdir (DIR * dirp)
  157. {
  158.   errno = 0;
  159.  
  160.   /* Check for valid DIR struct. */
  161.   if (!dirp)
  162.     {
  163.       errno = EFAULT;
  164.       return (struct dirent *) 0;
  165.     }
  166.  
  167.   if (dirp->dd_dir.d_name != dirp->dd_dta.cFileName)
  168.     {
  169.       /* The structure does not seem to be set up correctly. */
  170.       errno = EINVAL;
  171.       return (struct dirent *) 0;
  172.     }
  173.  
  174.   if (dirp->dd_stat < 0)
  175.     {
  176.       /* We have already returned all files in the directory
  177.        * (or the structure has an invalid dd_stat). */
  178.       return (struct dirent *) 0;
  179.     }
  180.   else if (dirp->dd_stat == 0)
  181.     {
  182.       /* We haven't started the search yet. */
  183.       /* Start the search */
  184.       dirp->dd_handle = (long)FindFirstFile (dirp->dd_name, &(dirp->dd_dta));
  185.  
  186.         if (dirp->dd_handle == -1)
  187.     {
  188.       /* Whoops! Seems there are no files in that
  189.        * directory. */
  190.       dirp->dd_stat = -1;
  191.     }
  192.       else
  193.     {
  194.       dirp->dd_stat = 1;
  195.     }
  196.     }
  197.   else
  198.     {
  199.       /* Get the next search entry. */
  200.       if (FindNextFile ((HANDLE)dirp->dd_handle, &(dirp->dd_dta)))
  201.     {
  202.       /* We are off the end or otherwise error. */
  203.       FindClose ((HANDLE)dirp->dd_handle);
  204.       dirp->dd_handle = -1;
  205.       dirp->dd_stat = -1;
  206.     }
  207.       else
  208.     {
  209.       /* Update the status to indicate the correct
  210.        * number. */
  211.       dirp->dd_stat++;
  212.     }
  213.     }
  214.  
  215.   if (dirp->dd_stat > 0)
  216.     {
  217.       /* Successfully got an entry. Everything about the file is
  218.        * already appropriately filled in except the length of the
  219.        * file name. */
  220.       dirp->dd_dir.d_namlen = strlen (dirp->dd_dir.d_name);
  221.       return &dirp->dd_dir;
  222.     }
  223.  
  224.   return (struct dirent *) 0;
  225. }
  226.  
  227.  
  228. /*
  229.  * closedir
  230.  *
  231.  * Frees up resources allocated by opendir.
  232.  */
  233. int
  234. closedir (DIR * dirp)
  235. {
  236.   int rc;
  237.  
  238.   errno = 0;
  239.   rc = 0;
  240.  
  241.   if (!dirp)
  242.     {
  243.       errno = EFAULT;
  244.       return -1;
  245.     }
  246.  
  247.   if (dirp->dd_handle != -1)
  248.     {
  249.       rc = FindClose ((HANDLE)dirp->dd_handle);
  250.     }
  251.  
  252.   /* Delete the dir structure. */
  253.   free (dirp);
  254.  
  255.   return rc;
  256. }
  257.  
  258. /*
  259.  * rewinddir
  260.  *
  261.  * Return to the beginning of the directory "stream". We simply call findclose
  262.  * and then reset things like an opendir.
  263.  */
  264. void
  265. rewinddir (DIR * dirp)
  266. {
  267.   errno = 0;
  268.  
  269.   if (!dirp)
  270.     {
  271.       errno = EFAULT;
  272.       return;
  273.     }
  274.  
  275.   if (dirp->dd_handle != -1)
  276.     {
  277.       FindClose ((HANDLE)dirp->dd_handle);
  278.     }
  279.  
  280.   dirp->dd_handle = -1;
  281.   dirp->dd_stat = 0;
  282. }
  283.  
  284. /*
  285.  * telldir
  286.  *
  287.  * Returns the "position" in the "directory stream" which can be used with
  288.  * seekdir to go back to an old entry. We simply return the value in stat.
  289.  */
  290. long
  291. telldir (DIR * dirp)
  292. {
  293.   errno = 0;
  294.  
  295.   if (!dirp)
  296.     {
  297.       errno = EFAULT;
  298.       return -1;
  299.     }
  300.   return dirp->dd_stat;
  301. }
  302.  
  303. /*
  304.  * seekdir
  305.  *
  306.  * Seek to an entry previously returned by telldir. We rewind the directory
  307.  * and call readdir repeatedly until either dd_stat is the position number
  308.  * or -1 (off the end). This is not perfect, in that the directory may
  309.  * have changed while we weren't looking. But that is probably the case with
  310.  * any such system.
  311.  */
  312. void
  313. seekdir (DIR * dirp, long lPos)
  314. {
  315.   errno = 0;
  316.  
  317.   if (!dirp)
  318.     {
  319.       errno = EFAULT;
  320.       return;
  321.     }
  322.  
  323.   if (lPos < -1)
  324.     {
  325.       /* Seeking to an invalid position. */
  326.       errno = EINVAL;
  327.       return;
  328.     }
  329.   else if (lPos == -1)
  330.     {
  331.       /* Seek past end. */
  332.       if (dirp->dd_handle != -1)
  333.     {
  334.       FindClose ((HANDLE)dirp->dd_handle);
  335.     }
  336.       dirp->dd_handle = -1;
  337.       dirp->dd_stat = -1;
  338.     }
  339.   else
  340.     {
  341.       /* Rewind and read forward to the appropriate index. */
  342.       rewinddir (dirp);
  343.  
  344.       while ((dirp->dd_stat < lPos) && readdir (dirp))
  345.     ;
  346.     }
  347. }
  348.